package client

import (
	"fmt"
	"gitee.com/qzcsu/go-web-study/client/etcd"
	"gitee.com/qzcsu/go-web-study/grpc/impl"
	"gitee.com/qzcsu/go-web-study/grpc/proto/pandago"
	clientv3 "go.etcd.io/etcd/client/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"log"
	"net"
	"time"
)

/**
1. 服务注册，获取本地ip，rpc端口，put 注册至 etcd。解除

*/

var (
	EtcdCli   = &clientv3.Client{}
	grpcPort  = 8339
	svrName   = "go-web-study"
	discovery *etcd.Discovery
)

func registerEtcd() {
	addr := ""
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, value := range addrs {
		if ipnet, ok := value.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				addr = ipnet.IP.String()
			}
		}
	}
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:         []string{"10.248.174.155:2371", "10.248.174.155:2381", "10.248.174.155:2391"},
		DialTimeout:       5 * time.Second,
		DialKeepAliveTime: 1 * time.Minute,
	})
	if err != nil {
		// handle error!
		log.Fatalf("get etcd client init error %v", err)
	}
	register := etcd.NewRegister(svrName, cli, addr, grpcPort)
	err = register.RegV2()
	if err != nil {
		log.Fatalf("server rgister error %v", err)
	}
	log.Println("服务注册成功")
	go func() {
		// 监听本地的8972端口
		lis, err := net.Listen("tcp", ":8339")
		if err != nil {
			fmt.Printf("failed to listen: %v", err)
			return
		}
		s := grpc.NewServer() // 创建gRPC服务器
		// 将服务描述(server)及其具体实现(PandaGoSrv)注册到 gRPC 中去.
		// 内部使用的是一个 map 结构存储，类似 HTTP server。
		pandago.RegisterPandaGoServiceServer(s, &impl.PandaGoSrv{})
		reflection.Register(s) //在给定的gRPC服务器上注册服务器反射服务
		// Serve方法在lis上接受传入连接，为每个连接创建一个ServerTransport和server的goroutine。
		// 该goroutine读取gRPC请求，然后调用已注册的处理程序来响应它们。
		log.Println("grpc server 启动成功")
		err = s.Serve(lis)
		if err != nil {
			fmt.Printf("failed to serve: %v", err)
			return
		}
	}()
	EtcdCli = cli
}

func GetGrpcSvrCli(svrName string) (*etcd.NodeInfo, error) {
	if discovery == nil {
		discovery = etcd.NewDiscovery(EtcdCli)
		go func() {
			discovery.Watch()
		}()
	}
	node := discovery.GetNode(svrName)
	return node, nil
}
